package rmhc.gui {
	import flash.display.Bitmap;
	import flash.display.BitmapData;
	import flash.display.Loader;
	import flash.display.Sprite;
	import flash.display.Stage;
	import flash.display.StageAlign;
	import flash.events.*;
	import flash.geom.Matrix;
	import flash.geom.Point;
	import flash.geom.Rectangle;
	import flash.net.URLRequest;
	
	import rmhc.design.ImageEditorDesign;
	import rmhc.design.ImageFrameDesign;
	import rmhc.gui.ScaleRectangle;

    public class MergeManager extends ImageEditorDesign {
		static public var palmK:Number = 0.5;
		private var loader:Loader;
		private var canvasBitmapData:BitmapData;
		public var canvas:Sprite;
		public var elementBitmapData:BitmapData;
		private var element:Sprite;
		private var canvasPath:String;
		private var elementPath:String;
		public var palmPath:String = "palm.png";
		private var mousePoint:Point;
		private var frame:ImageFrameDesign;
		private var minWidth:Number = 50;
		private var minHeight:Number ;
		private var rect:ScaleRectangle = new ScaleRectangle();
		private var maxWidth:Number;
		private var maxHeight:Number;
		///Width/Height у ладошки.
		private var kWH:Number;
		private var resizeK:Number;
		private var stageLink:Stage
		
		public function MergeManager(canvasBitmapData:BitmapData, elementPath:String = "palm.png", maxWidth:Number = 600, maxHeight:Number = 600)
		{
			trace("MergeManager:MergeManager: " +maxWidth+"x"+maxHeight);
			//trace("MergeManager:MergeManager: canvasBitmapData.width" +canvasBitmapData.width);
			this.canvasBitmapData = canvasBitmapData;
			this.maxHeight = maxHeight;
			this.maxWidth = maxWidth;
			this.elementPath = elementPath;
			loader = new Loader();
			loader.contentLoaderInfo.addEventListener(Event.COMPLETE, completeHandler);
			loader.contentLoaderInfo.addEventListener(Event.COMPLETE, completeHandler);
			var request:URLRequest = new URLRequest(elementPath);
			loader.load(request);
			addEventListener(Event.ADDED_TO_STAGE, addedToStage);
		}
		
		private function addedToStage(e:Event):void 
		{
			removeEventListener(Event.ADDED_TO_STAGE, addedToStage);
			stageLink = stage;
			stage.addEventListener(MouseEvent.MOUSE_UP, mouseUp);
		}
		  
		public function getElement():BitmapData
		{
			return elementBitmapData;
		}
		  
		private function setRect():void {
			rect.TL = new Point(element.x, element.y);
			rect.BR = new Point(element.x + element.width, element.y + element.height);
		}
		private function applyRect():void {
			element.x = rect.x;
			element.width = rect.width;
			element.y = rect.y;
			element.height = rect.height;
		}
        private function completeHandler(event:Event):void {
            //trace("completeHandler: " + event);
            loader.contentLoaderInfo.removeEventListener(Event.COMPLETE, completeHandler);
			elementBitmapData = (loader.content as Bitmap).bitmapData;
            start();
        }
		
		private function start():void 
		{
			customTrace("MergeManager:start: canvasBitmapData.width = "+canvasBitmapData.width );
			resizeK = 1;
			
			if (canvasBitmapData.width > maxWidth) {
				resizeK = maxWidth / canvasBitmapData.width;
			}
			if (canvasBitmapData.height * resizeK > maxHeight) {
				resizeK = maxHeight / canvasBitmapData.height;
			}
			customTrace("MergeManager:start: resizeK = " +resizeK);
			//canvasBitmapData = scaleBitmap(canvasBitmapData, resizeK, resizeK);
			canvas = new Sprite();
			canvas.addChild(new Bitmap(canvasBitmapData,"auto",true));
			if (resizeK != 1) {
				canvas.scaleX = resizeK;
				canvas.scaleY = resizeK;
			}
			element = new Sprite();
			element.x = 0;
			element.y = 0;
			element.mouseEnabled = false;
			element.addChild(new Bitmap(elementBitmapData,"auto",true));
			addChild(canvas);
			customTrace("MergeManager:start:" +width+"x"+height);
			kWH = element.width / element.height;
			//minWidth = element.width;
			minHeight = minWidth / kWH;
			//trace("ширина = "+)
			element.height = canvas.height * palmK;
			element.width = element.height * kWH;
			if (element.width < minWidth) {
				element.width = minWidth;
				element.height = minHeight;
			}
			addEventListener(MouseEvent.MOUSE_DOWN, mouseDown);
			frame = new ImageFrameDesign();
			addChild(frame);
			addChild(element);
			setRect();
			refreshFrame();
			setImage(canvas);
			addChild(frame);
			addChild(element);
			
			dispatchEvent(new Event(Event.COMPLETE));
		}
		
		private function mouseDown(event:MouseEvent):void 
		{
			var p:Point = globalToLocal(new Point(event.stageX, event.stageY));
			var e:Object = { stageX:p.x, stageY:p.y };
			mousePoint = new Point(element.x - e.stageX, element.y - e.stageY);
			switch (event.target) 
			{
				case frame.leftTop: {
					addEventListener(MouseEvent.MOUSE_MOVE, mouseMove_TL);
					break;
				}
				case frame.leftBottom: {
					addEventListener(MouseEvent.MOUSE_MOVE, mouseMove_BL);
					break;
				}
				case frame.rightBottom: {
					addEventListener(MouseEvent.MOUSE_MOVE, mouseMove_BR);
					break;
				}
				case frame.rightTop: {
					addEventListener(MouseEvent.MOUSE_MOVE, mouseMove_TR);
					break;
				}
				default: {
					stage.addEventListener(MouseEvent.MOUSE_MOVE, mouseMove_Move);
				}
				
			}
			
		}
		
		private function mouseUp(event:MouseEvent):void 
		{
			removeMouseMoveListeners();
		}
		
		private function removeMouseMoveListeners():void 
		{
			if(stageLink)
				stageLink.removeEventListener(MouseEvent.MOUSE_MOVE, mouseMove_Move);
			removeEventListener(MouseEvent.MOUSE_MOVE, mouseMove_TR);
			removeEventListener(MouseEvent.MOUSE_MOVE, mouseMove_TL);
			removeEventListener(MouseEvent.MOUSE_MOVE, mouseMove_BL);
			removeEventListener(MouseEvent.MOUSE_MOVE, mouseMove_BR);
		}
		private function mouseMove_Move(event:MouseEvent):void 
		{
			move(event);
			refreshFrame();
		}
		private function mouseMove_TL(event:MouseEvent):void 
		{
			resizeTL(event);
			refreshFrame();
		}
		private function mouseMove_TR(event:MouseEvent):void 
		{
			resizeTR(event);
			refreshFrame();
		}
		private function mouseMove_BL(event:MouseEvent):void 
		{
			resizeBL(event);
			refreshFrame();
		}
		private function mouseMove_BR(event:MouseEvent):void 
		{
			resizeBR(event);
			refreshFrame();
		}
		private function resizeBL(event:MouseEvent):void {
			var p:Point = globalToLocal(new Point(event.stageX, event.stageY));
			var e:Object = { stageX:p.x, stageY:p.y };			
			rect.BL = new Point(limit(e.stageX, 0, element.x + element.width - minWidth), limit(e.stageY, element.y + minHeight, canvas.height));
			if (rect.height * kWH > rect.width) {
				var newHeight:Number = rect.width / kWH;
				rect.BL = new Point(rect.x, rect.y + newHeight);
			}else {
				var newWidth:Number = rect.height * kWH;
				rect.BL = new Point(rect.x+rect.width-newWidth, rect.y+rect.height);
			}
			applyRect();
		}
		private function resizeBR(event:MouseEvent):void {
			var p:Point = globalToLocal(new Point(event.stageX, event.stageY));
			var e:Object = { stageX:p.x, stageY:p.y };			
			rect.BR = new Point(limit(e.stageX,element.x+minWidth,canvas.width), limit(e.stageY,element.y+minHeight,canvas.height));
			if (rect.height * kWH > rect.width) {
				var newHeight:Number = rect.width / kWH;
				rect.BR = new Point(rect.x+rect.width, rect.y + newHeight);
			}else {
				var newWidth:Number = rect.height * kWH;
				rect.BR = new Point(rect.x+newWidth, rect.y+rect.height);
			}
			applyRect();
		}
		private function resizeTR(event:MouseEvent):void {
			var p:Point = globalToLocal(new Point(event.stageX, event.stageY));
			var e:Object = { stageX:p.x, stageY:p.y };			
			rect.TR = new Point(limit(e.stageX,element.x+minWidth,canvas.width), limit(e.stageY,0,element.y+element.height-minHeight));
			if (rect.height * kWH > rect.width) {
				var newHeight:Number = rect.width / kWH;
				rect.TR = new Point(rect.x+rect.width, rect.y +rect.height-newHeight);
			}else {
				var newWidth:Number = rect.height * kWH;
				rect.TR = new Point(rect.x+newWidth, rect.y);
			}
			applyRect();
		}
		
		private function resizeTL(event:MouseEvent):void {
			var p:Point = globalToLocal(new Point(event.stageX, event.stageY));
			var e:Object = { stageX:p.x, stageY:p.y };			
			rect.TL = new Point(limit(e.stageX, 0, element.x + element.width - minWidth), limit(e.stageY, 0, element.y + element.height - minHeight));
			if (rect.height * kWH > rect.width) {
				var newHeight:Number = rect.width / kWH;
				rect.TL = new Point(rect.x, rect.y +rect.height-newHeight);
			}else {
				var newWidth:Number = rect.height * kWH;
				rect.TL = new Point(rect.x+rect.width-newWidth, rect.y);
			}
			applyRect();
		}
		private function move(event:MouseEvent):void {
			var p:Point = globalToLocal(new Point(event.stageX, event.stageY));
			var e:Object = { stageX:p.x, stageY:p.y };
			var x:Number = mousePoint.x + e.stageX;
			var y:Number = mousePoint.y + e.stageY;
			x = x<0?0:(x>canvas.width-element.width?canvas.width-element.width:x);
			y = y<0?0:(y>canvas.height-element.height?canvas.height-element.height:y);
			element.x = x;
			element.y = y;
			setRect();
		}
		private function refreshFrame():void 
		{
			//frame.frameSize = new Rectangle(element.x, element.y, element.x + element.width, element.height + element.y);
			frame.frameSize = new Rectangle(0, 0, element.width, element.height);
			frame.x = element.x;
			frame.y = element.y;
		}
		
		public function getMerged():BitmapData  {
			var result:BitmapData;
			if(elementBitmapData){
				result = bitmapDataMerge(canvasBitmapData, elementBitmapData, element.x / canvas.scaleX, element.y / canvas.scaleY, element.scaleX / canvas.scaleX, element.scaleY / canvas.scaleY);
			}else {
				result = canvasBitmapData;
			}
			trace(result.width + "x" + result.height);
			return result;
		}
		static public function limit(value:Number, min:Number, max:Number):Number {
			return (value<min)?(min):(value>max?(max):(value));
		}
    	static public function bitmapDataMerge(canvas:BitmapData,element:BitmapData,positionX:int,positionY:int,scaleX:Number,scaleY:Number):BitmapData {
			var result:BitmapData = canvas.clone();
			
			result.draw(element,new Matrix(scaleX,0,0,scaleY,positionX,positionY),null,null,null,true);
			return result;
		}
		static public function scaleBitmap(original:BitmapData, scaleX:Number, scaleY:Number):BitmapData {
			var result:BitmapData = new BitmapData(original.width * scaleX, original.height * scaleY);
			result.lock();
			for (var y:int = 0; y < result.height; y++) 
			{
				for (var x:int = 0; x < result.width; x++) 
				{
					result.setPixel32(x, y, original.getPixel32(x / scaleX, y / scaleY));
				}
			}
			result.unlock();
			return result;			
		}
    }
}